﻿using Module.NumberGame.Common;
using Prism.Commands;
using Prism.Events;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;

namespace Module.NumberGame.ViewModels
{
    public class NumberGameAppViewModel : BindableBase
    {
        private readonly IEventAggregator Ea;
        public DelegateCommand ResetCommand { get; private set; }
        public DelegateCommand MoveTest { get; private set; }
        const int TotalRow = 5;
        const int MaxNumber = 4;
        int[,] BoardData = new int[TotalRow, TotalRow];

        private int score;
        public int Score
        {
            get { return score; }
            set { SetProperty(ref score, value); }
        }

        private bool movePiece_1;
        public bool MovePiece_1
        {
            get { return movePiece_1; }
            set { SetProperty(ref movePiece_1, value); }
        }
        private bool pieceMoveLeft;
        public bool PieceMoveLeft
        {
            get { return pieceMoveLeft; }
            set { SetProperty(ref pieceMoveLeft, value); }
        }
        private bool pieceMoveRight;
        public bool PieceMoveRight
        {
            get { return pieceMoveRight; }
            set { SetProperty(ref pieceMoveRight, value);}
        }
        private bool pieceMoveUp;
        public bool PieceMoveUp
        {
            get { return pieceMoveUp; }
            set { SetProperty(ref pieceMoveUp, value); }
        }
        private bool pieceMoveDown;
        public bool PieceMoveDown
        {
            get { return pieceMoveDown; }
            set { SetProperty(ref pieceMoveDown, value); }
        }

        public NumberGameAppViewModel(IEventAggregator ea)
        {
            this.Ea = ea;
            Ea.GetEvent<NumberMessageEvent>().Subscribe(MouseMoveProcess,ThreadOption.UIThread);
            ResetCommand = new DelegateCommand(ResetButtonClick);
            MoveTest=new DelegateCommand(TestMoveAnimation);
            for (int i = 0; i < TotalRow; i++)
                for (int j = 0; j < TotalRow; j++)
                {
                    BoardData[i, j] = 0;
                    if (i is > 0 and < 4 && j is > 0 and < 4) BoardData[i, j] = 1;
                }
            Score = 0;
            PieceMoveDown = false; PieceMoveLeft = false; PieceMoveRight = false; PieceMoveUp = false;
        }

        private void TestMoveAnimation()
        {
            MovePiece_1=!MovePiece_1;
        }

        private void ResetButtonClick()
        {
            //Ea.GetEvent<NumberMessageEvent>().Publish(new NumberMessage() { Content = "ResetGame" });
        }
        private void ReStart()
        {
            for (int i = 0; i < TotalRow; i++)
            {
                for (int j = 0; j < TotalRow; j++)
                {
                    BoardData[i, j] = 0;
                    if (i is > 0 and < 4 && j is > 0 and < 4) BoardData[i, j] = 1;
                }
            }
            Score = 0;
        }
        private void MouseMoveProcess(NumberMessage obj)
        {
            ProcessPieces(obj.MouseDisX, obj.MouseDisY);
            Ea.GetEvent<NumberBoardDataEvent>().Publish(new NumberMessage() { BoardDataMessage = BoardData });
        }


        private void ProcessPieces(double disx, double disy)
        {
            int[] resl = new int[TotalRow];
            Random randnumber = new();
            int newNum = randnumber.Next(1, MaxNumber);
            int oldtotal = GetNotZeroNumber();
            PieceMoveDown= false; PieceMoveLeft = false; PieceMoveRight = false; PieceMoveUp =false;

            if (Math.Abs(disx) > Math.Abs(disy)) // 水平移动量大于垂直移动量时，只水平移动
            {
                if (disx < 0) // 向左移动
                {
                    PieceMoveLeft = true;
                    for (int row = 0; row < TotalRow; row++)
                    {
                        resl = ArrayChange(BoardData[0, row], BoardData[1, row], BoardData[2, row], BoardData[3, row], BoardData[4, row]);
                        BoardData[0, row] = resl[0];
                        BoardData[1, row] = resl[1];
                        BoardData[2, row] = resl[2];
                        BoardData[3, row] = resl[3];
                        BoardData[4, row] = resl[4];
                    }
                    if (oldtotal != GetNotZeroNumber()) // 如果数字有合并，增加一个新的数字
                    {
                        Random random = new Random();
                        int index = random.Next(0, 100) % 5;
                        for (int i = 0; i < TotalRow; i++)
                        {
                            if (BoardData[4, index] > 0)
                            {
                                index = (index + 1) % 5;
                            }
                            else
                            {
                                BoardData[4, index] = newNum;
                                break;
                            }
                        }
                    }
                }
                else // 向右移动
                {
                    PieceMoveRight = true;
                    for (int row = 0; row < TotalRow; row++)
                    {
                        resl = ArrayChange(BoardData[4, row], BoardData[3, row], BoardData[2, row], BoardData[1, row], BoardData[0, row]);
                        BoardData[4, row] = resl[0];
                        BoardData[3, row] = resl[1];
                        BoardData[2, row] = resl[2];
                        BoardData[1, row] = resl[3];
                        BoardData[0, row] = resl[4];
                    }
                    if (oldtotal != GetNotZeroNumber()) // 如果数字有合并，增加一个新的数字
                    {
                        Random random = new Random();
                        int index = random.Next(0, 100) % 5;
                        for (int i = 0; i < TotalRow; i++)
                        {
                            if (BoardData[0, index] > 0)
                            {
                                index = (index + 1) % 5;
                            }
                            else
                            {
                                BoardData[0, index] = newNum;
                                break;
                            }
                        }
                    }
                }
            }
            else // 垂直移动
            {
                if (disy < 0) // 向上移动
                {
                    PieceMoveUp = true;
                    for (int col = 0; col < TotalRow; col++)
                    {
                        resl = ArrayChange(BoardData[col, 0], BoardData[col, 1], BoardData[col, 2], BoardData[col, 3], BoardData[col, 4]);
                        BoardData[col, 0] = resl[0];
                        BoardData[col, 1] = resl[1];
                        BoardData[col, 2] = resl[2];
                        BoardData[col, 3] = resl[3];
                        BoardData[col, 4] = resl[4];
                    }
                    if (oldtotal != GetNotZeroNumber()) // 如果数字有合并，增加一个新的数字
                    {
                        Random random = new Random();
                        int index = random.Next(0, 100) % 5;
                        for (int i = 0; i < TotalRow; i++)
                        {
                            if (BoardData[index, 4] > 0)
                            {
                                index = (index + 1) % 5;
                            }
                            else
                            {
                                BoardData[index, 4] = newNum;
                                break;
                            }
                        }
                    }
                }
                else // 向下移动
                {
                    PieceMoveDown = true;
                    for (int col = 0; col < TotalRow; col++)
                    {
                        resl = ArrayChange(BoardData[col, 4], BoardData[col, 3], BoardData[col, 2], BoardData[col, 1], BoardData[col, 0]);
                        BoardData[col, 4] = resl[0];
                        BoardData[col, 3] = resl[1];
                        BoardData[col, 2] = resl[2];
                        BoardData[col, 1] = resl[3];
                        BoardData[col, 0] = resl[4];
                    }
                    if (oldtotal != GetNotZeroNumber()) // 如果数字有合并，增加一个新的数字
                    {
                        Random random = new Random();
                        int index = random.Next(0, 100) % 5;
                        for (int i = 0; i < TotalRow; i++)
                        {
                            if (BoardData[index, 0] > 0)
                            {
                                index = (index + 1) % 5;
                            }
                            else
                            {
                                BoardData[index, 0] = newNum;
                                break;
                            }
                        }
                    }
                }
            }

            Score = GetScore();
        }

        private int[] ArrayChange(int a, int b, int c, int d, int e)
        {
            int[] resl = new int[TotalRow];
            for (int i = 0; i < TotalRow - 1; i++) // 清除零位
            {
                if (a == 0)
                {
                    a = b; b = c; c = d; d = e; e = 0;
                }
                if (b == 0)
                {
                    b = c; c = d; d = e; e = 0;
                }
                if (c == 0)
                {
                    c = d; d = e; e = 0;
                }
                if (d == 0)
                {
                    d = e; e = 0;
                }
            }

            if (a > 0 && a == b)
            {
                a++; b = 0;
            }
            if (b > 0 && b == c)
            {
                b++; c = 0;
            }
            if (c > 0 && c == d)
            {
                c++; d = 0;
            }
            if (d > 0 && d == e)
            {
                d++; e = 0;
            }

            for (int i = 0; i < TotalRow - 1; i++) // 清除零位
            {
                if (a == 0)
                {
                    a = b; b = c; c = d; d = e; e = 0;
                }
                if (b == 0)
                {
                    b = c; c = d; d = e; e = 0;
                }
                if (c == 0)
                {
                    c = d; d = e; e = 0;
                }
                if (d == 0)
                {
                    d = e; e = 0;
                }
            }
            resl[0] = a;
            resl[1] = b;
            resl[2] = c;
            resl[3] = d;
            resl[4] = e;
            return resl;
        }

        private int GetScore()
        {
            int score = 0;
            for (int i = 0; i < TotalRow; i++)
            {
                for (int j = 0; j < TotalRow; j++)
                {
                    int num = BoardData[i, j];
                    if (num > 2)
                    {
                        score += (int)Math.Pow(3, num);
                    }
                }
            }
            return score;
        }
        private int GetNotZeroNumber()
        {
            int total = 0;
            for (int i = 0; i < TotalRow; i++)
            {
                for (int j = 0; j < TotalRow; j++)
                {
                    if (BoardData[i, j] > 0)
                    {
                        total += i + j * 5;
                    }
                }
            }
            return total;
        }
    }
}
